package cc.cix.hq.org.service.impl;

import cc.cix.hq.common.core.entity.QueryRequest;
import cc.cix.hq.common.core.entity.org.Role;
import cc.cix.hq.common.core.entity.org.RoleMenu;
import cc.cix.hq.common.core.entity.org.UserRole;
import cc.cix.hq.common.core.utils.HqUtil;
import cc.cix.hq.org.mapper.RoleMapper;
import cc.cix.hq.org.service.IRoleMenuService;
import cc.cix.hq.org.service.IRoleService;
import cc.cix.hq.org.service.IUserRoleService;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author cix
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    private final IRoleMenuService roleMenuService;
    private final IUserRoleService userRoleService;

    @Override
    public cc.cix.hq.common.core.entity.Page<Role> listRole(Role role, QueryRequest request) {
        IPage<Role> page = lambdaQuery()
                .eq(ObjectUtil.isNotNull(role.getRoleName()), Role::getRoleName, role.getRoleName())
                .orderByAsc(Role::getId)
                .page(new Page<>(request.getPageNum(), request.getPageSize()));

        page.getRecords().forEach(i -> {
            List<Long> menuIds = roleMenuService.lambdaQuery()
                    .eq(RoleMenu::getRoleId, i.getId())
                    .list()
                    .stream()
                    .map(RoleMenu::getMenuId)
                    .collect(Collectors.toList());
            i.setMenuIds(menuIds);
        });

        return HqUtil.getPage(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createRole(Role role) {
        save(role);

        if (!role.getMenuIds().isEmpty()) {
            setRoleMenus(role);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRoleByIds(List<String> roleIds) {
        removeByIds(roleIds);

        roleMenuService.lambdaUpdate().in(RoleMenu::getRoleId, roleIds).remove();
        userRoleService.lambdaUpdate().in(UserRole::getRoleId, roleIds).remove();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateRole(Role role) {
        role.setRoleName(null);
        updateById(role);

        roleMenuService.lambdaUpdate().eq(RoleMenu::getRoleId, role.getId()).remove();
        if (!role.getMenuIds().isEmpty()) {
            setRoleMenus(role);
        }
    }

    private void setRoleMenus(Role role) {
        List<RoleMenu> roleMenus = new ArrayList<>();
        role.getMenuIds().forEach(i -> {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setMenuId(i);
            roleMenu.setRoleId(role.getId());
            roleMenus.add(roleMenu);
        });

        roleMenuService.saveBatch(roleMenus);
    }

}
